import {
    _decorator,
    Component,
    Node,
    sp,
    Button,
    director,
    tween,
} from 'cc';
const { ccclass, property } = _decorator;

@ccclass('SpineReversePlayer')
export class SpineReversePlayer extends Component {
    @property({
        type: sp.Skeleton,
        tooltip: '拖拽你的Spine动画组件到这里',
    })
    spineAnimation: sp.Skeleton = null;

    @property({
        type: Button,
        tooltip: '拖拽一个按钮组件到这里，用于切换播放方向',
    })
    toggleButton: Button = null;

    private _isReversed: boolean = false; // 标记当前是否处于倒放状态
    private _manualReverseMode: boolean = false; // 标记是否启用手动倒放模式

    onLoad() {
        // 确保Spine动画组件和按钮已正确赋值
        if (!this.spineAnimation) {
            console.error(
                'Spine animation component is not assigned! Please drag the Spine node to the property field.',
            );
            return;
        }
        if (!this.toggleButton) {
            console.error(
                'Toggle button is not assigned! Please drag a Button node to the property field.',
            );
            return;
        }

        // 为按钮添加点击事件监听器
        this.toggleButton.node.on(
            Button.EventType.CLICK,
            this.onToggleButtonClick,
            this,
        );
    }

    /**
     * 按钮点击事件处理函数，用于切换Spine动画的播放方向
     */
    onToggleButtonClick() {
        this._isReversed = !this._isReversed; // 切换倒放状态

        if (this._isReversed) {
            this.playRevert();
        } else {
            this.playNormal();
        }
    }

    // 使用Tween替代update()
    playRevertByTween(callBack?: VoidFunction) {
        this.spineAnimation.timeScale = 0;
        const trackEntry = this.spineAnimation.getCurrent(0);
        if (trackEntry && trackEntry.animation) {
            const duration = trackEntry.animation.duration;
            const time = { num: duration };
            trackEntry.trackTime = duration;
            tween(time)
                .to(
                    duration,
                    { num: 0 },
                    {
                        onUpdate: () => {
                            trackEntry.trackTime = time.num;
                            this.spineAnimation
                                .getState()
                                .apply(this.spineAnimation._skeleton);
                            this.spineAnimation._skeleton.updateWorldTransform();
                        },
                    },
                )

                .call(() => {
                    trackEntry.trackTime = 0;
                    this.spineAnimation
                        .getState()
                        .apply(this.spineAnimation._skeleton);
                    this.spineAnimation._skeleton.updateWorldTransform();
                    this.spineAnimation.getState().clearTracks();
                    this.spineAnimation.timeScale = 1;
                    callBack?.();
                })
                .start();
        }
    }

    // 进入手动倒放模式
    playRevert() {
        this._manualReverseMode = true;
        // 暂停Spine内部的时间推进，由我们手动控制
        this.spineAnimation.timeScale = 0;
        // 获取当前动画的 TrackEntry，并将其播放时间设置为动画的结束时间，以便从后往前播放
        const trackEntry = this.spineAnimation.getCurrent(0);
        if (trackEntry && trackEntry.animation) {
            trackEntry.trackTime = trackEntry.animation.duration;
        }
    }
    // 退出手动倒放模式
    playNormal() {
        this._manualReverseMode = false;
        // this.spineAnimation.timeScale = 1; // 恢复正常正向播放
        const name = this.spineAnimation.animation;
        this.spineAnimation.setAnimation(0, name, false);
    }

    update(dt: number) {
        // 只有在手动倒放模式下才执行
        if (!this._manualReverseMode || !this.spineAnimation) {
            return;
        }
        const trackEntry = this.spineAnimation.getCurrent(0);
        if (trackEntry && trackEntry.animation) {
            // 手动减少动画的播放时间
            trackEntry.trackTime -= dt;

            // 处理倒放时的循环逻辑
            if (trackEntry.trackTime < 0) {
                if (trackEntry.loop) {
                    // 如果设置了循环，则将时间跳回到动画的末尾，实现循环倒放
                    trackEntry.trackTime = trackEntry.animation.duration;
                } else {
                    trackEntry.trackTime = 0;
                    this.spineAnimation
                        .getState()
                        .apply(this.spineAnimation._skeleton);
                    this.spineAnimation._skeleton.updateWorldTransform();

                    // 停止手动更新
                    this._manualReverseMode = false;
                    this.spineAnimation.getState().clearTracks();
                    this.spineAnimation.timeScale = 1;
                    return;
                }
            }

            // 将动画状态应用到骨骼上，使其显示在当前 trackTime 对应的帧
            // `state.apply` 会根据 trackEntry.trackTime 来更新骨骼姿态
            this.spineAnimation
                .getState()
                .apply(this.spineAnimation._skeleton);
            // 更新骨骼的世界变换（位置、旋转、缩放），这对于渲染是必要的
            this.spineAnimation._skeleton.updateWorldTransform();
        }
    }

    onDestroy() {
        // 移除按钮事件监听器，避免内存泄漏
        if (this.toggleButton && this.toggleButton.node) {
            this.toggleButton.node.off(
                Button.EventType.CLICK,
                this.onToggleButtonClick,
                this,
            );
        }
    }
}
